package com.shopping.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shopping.dto.UserDTO;
import com.shopping.dto.UserQueryDTO;
import com.shopping.dto.UserUpdateDTO;
import com.shopping.dto.PasswordResetDTO;
import com.shopping.entity.User;
import com.shopping.exception.BusinessException;
import com.shopping.mapper.UserMapper;
import com.shopping.security.JwtUtil;
import com.shopping.service.UserService;
import com.shopping.util.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.stream.Collectors;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import org.springframework.security.core.context.SecurityContextHolder;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;

    @Resource
    private JwtUtil jwtUtil;

    public UserServiceImpl(@Lazy PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public Page<UserDTO> getUserList(UserQueryDTO queryDTO) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        // 添加查询条件
        if (StringUtils.hasText(queryDTO.getUsername())) {
            wrapper.like(User::getUsername, queryDTO.getUsername());
        }
        if (StringUtils.hasText(queryDTO.getPhone())) {
            wrapper.like(User::getPhone, queryDTO.getPhone());
        }
        if (queryDTO.getLevel() != null) {
            wrapper.eq(User::getLevel, queryDTO.getLevel());
        }
        if (queryDTO.getGender() != null) {
            wrapper.eq(User::getGender, queryDTO.getGender());
        }

        // 分页查询
        Page<User> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        Page<User> userPage = this.page(page, wrapper);

        // 转换为DTO
        Page<UserDTO> dtoPage = new Page<>();
        BeanUtils.copyProperties(userPage, dtoPage, "records");
        dtoPage.setRecords(userPage.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList()));

        return dtoPage;
    }

    @Override
    public UserDTO getUserById(Long id) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return convertToDTO(user);
    }

    @Override
    @Transactional
    public UserDTO updateUser(Long id, UserUpdateDTO updateDTO) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 检查手机号是否已存在
        if (!user.getPhone().equals(updateDTO.getPhone())) {
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getPhone, updateDTO.getPhone());
            if (this.count(wrapper) > 0) {
                throw new BusinessException("手机号已存在");
            }
        }

        // 检查邮箱是否已存在
        if (!user.getEmail().equals(updateDTO.getEmail())) {
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getEmail, updateDTO.getEmail());
            if (this.count(wrapper) > 0) {
                throw new BusinessException("邮箱已存在");
            }
        }

        // 更新用户信息
        user.setPhone(updateDTO.getPhone());
        user.setEmail(updateDTO.getEmail());
        user.setGender(updateDTO.getGender());
        user.setLevel(updateDTO.getLevel());
        user.setPoints(updateDTO.getPoints());
        user.setBirthday(updateDTO.getBirthday()); // 新增：同步生日字段

        this.updateById(user);
        return convertToDTO(user);
    }

    @Override
    @Transactional
    public void resetPassword(Long id, PasswordResetDTO resetDTO) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setPassword(passwordEncoder.encode(resetDTO.getNewPassword()));
        this.updateById(user);
    }

    @Override
    @Transactional
    public void toggleUserStatus(Long id) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setStatus(user.getStatus() == User.UserStatus.ACTIVE ?
                User.UserStatus.DISABLED : User.UserStatus.ACTIVE);
        this.updateById(user);
    }

    @Override
    @Transactional
    public boolean register(User user) {
        // 检查用户名是否已存在
        if (findByUsername(user.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        // 检查手机号是否已存在
        LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
        phoneWrapper.eq(User::getPhone, user.getPhone());
        if (this.count(phoneWrapper) > 0) {
            throw new BusinessException("手机号已存在");
        }

        // 检查邮箱是否已存在
        LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
        emailWrapper.eq(User::getEmail, user.getEmail());
        if (this.count(emailWrapper) > 0) {
            throw new BusinessException("邮箱已存在");
        }

        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 设置默认值
        user.setLevel(User.UserLevel.NORMAL);
        user.setPoints(0);
        user.setStatus(User.UserStatus.ACTIVE);

        return this.save(user);
    }

    @Override
    public String login(String username, String password) {
        User user = findByUsername(username);
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }

        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }

        if (user.getStatus() == User.UserStatus.DISABLED) {
            throw new BusinessException("账号已被禁用");
        }

        // 创建UserDetails对象
        boolean isAdmin = "admin".equals(username) && User.UserLevel.DIAMOND.equals(user.getLevel());  // 修改为与 CustomUserDetailsService 一致的判断逻辑
        UserDetails userDetails = new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                true, // enabled
                true, // accountNonExpired
                true, // credentialsNonExpired
                true, // accountNonLocked
                Collections.singletonList(new SimpleGrantedAuthority(isAdmin ? "ROLE_ADMIN" : "ROLE_USER"))
        );

        // 生成JWT token
        return jwtUtil.generateToken(userDetails);
    }

    @Override
    public User findByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return this.getOne(wrapper);
    }

    @Override
    @Transactional
    public boolean updatePoints(Long userId, Integer points) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 更新积分
        user.setPoints(user.getPoints() + points);

        // 根据新积分自动更新等级
        User.UserLevel newLevel = User.UserLevel.getLevelByPoints(user.getPoints());
        user.setLevel(newLevel);

        return this.updateById(user);
    }

    @Override
    @Transactional
    public boolean updateLevel(Long userId) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 根据积分更新等级
        User.UserLevel newLevel = User.UserLevel.getLevelByPoints(user.getPoints());
        user.setLevel(newLevel);

        return this.updateById(user);
    }

    @Override
    public Object getUserStatistics() {
        // 获取总用户数
        long totalUsers = this.count();

        // 获取今日新增用户数
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LambdaQueryWrapper<User> newUserWrapper = new LambdaQueryWrapper<>();
        newUserWrapper.ge(User::getCreateTime, startOfDay);
        long newUsers = this.count(newUserWrapper);

        // 获取各等级用户数
        LambdaQueryWrapper<User> normalWrapper = new LambdaQueryWrapper<>();
        normalWrapper.eq(User::getLevel, User.UserLevel.NORMAL);
        long normalUsers = this.count(normalWrapper);

        LambdaQueryWrapper<User> silverWrapper = new LambdaQueryWrapper<>();
        silverWrapper.eq(User::getLevel, User.UserLevel.SILVER);
        long silverUsers = this.count(silverWrapper);

        LambdaQueryWrapper<User> goldWrapper = new LambdaQueryWrapper<>();
        goldWrapper.eq(User::getLevel, User.UserLevel.GOLD);
        long goldUsers = this.count(goldWrapper);

        LambdaQueryWrapper<User> diamondWrapper = new LambdaQueryWrapper<>();
        diamondWrapper.eq(User::getLevel, User.UserLevel.DIAMOND);
        long diamondUsers = this.count(diamondWrapper);

        // 获取活跃用户数（最近30天有登录的用户）
        LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);
        LambdaQueryWrapper<User> activeWrapper = new LambdaQueryWrapper<>();
        activeWrapper.ge(User::getLastLoginTime, thirtyDaysAgo);
        long activeUsers = this.count(activeWrapper);

        // 计算用户活跃度百分比
        double activeUsersPercentage = totalUsers > 0 ?
                (double) activeUsers / totalUsers * 100 : 0;

        // 计算上月同期活跃度
        LocalDateTime sixtyDaysAgo = LocalDateTime.now().minusDays(60);
        LocalDateTime lastMonthEnd = LocalDateTime.now().minusDays(30);
        LambdaQueryWrapper<User> lastMonthActiveWrapper = new LambdaQueryWrapper<>();
        lastMonthActiveWrapper.between(User::getLastLoginTime, sixtyDaysAgo, lastMonthEnd);
        long lastMonthActiveUsers = this.count(lastMonthActiveWrapper);
        double lastMonthActiveUsersPercentage = totalUsers > 0 ?
                (double) lastMonthActiveUsers / totalUsers * 100 : 0;

        // 计算活跃度变化
        double activeUsersChange = lastMonthActiveUsersPercentage > 0 ?
                ((activeUsersPercentage - lastMonthActiveUsersPercentage) / lastMonthActiveUsersPercentage) * 100 : 0;

        // 创建统计结果Map
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalUsers", totalUsers);
        statistics.put("newUsers", newUsers);
        statistics.put("normalUsers", normalUsers);
        statistics.put("silverUsers", silverUsers);
        statistics.put("goldUsers", goldUsers);
        statistics.put("diamondUsers", diamondUsers);
        statistics.put("activeUsers", activeUsersPercentage);
        statistics.put("activeUsersChange", activeUsersChange);

        return statistics;
    }

    @Override
    public User getCurrentUser() {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            return null;
        }
        return this.getById(userId);
    }

    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(user, dto);
        return dto;
    }
} 